/* api */
import { getCustomerTagList } from '@src/api/SettingApi'
/* entity */
import CustomerTag from '@model/entity/CustomerTag'
/* enum */
import ComponentNameEnum from '@model/enum/ComponentNameEnum'
/* scss */
import '@src/modules/customer/view/components/CustomerTagEdit/CustomerTagEditDialog.scss'
/* util */
import Platform from '@src/util/platform'
import { isEmpty } from '@src/util/type'
import { fieldArrayToObject, FieldArrayToObjectKeyEnum } from '@src/util/array'
import { openTabForSettingCustomerView } from '@src/util/business/openTab'
/* vue */
import { Component, Emit, Prop } from 'vue-property-decorator'
import { CreateElement, VNode } from 'vue'
import VC from '@model/VC'
import { setCustomerTag, batchUpdateCustomerTag } from '@src/api/CustomerApi'
import * as _ from 'lodash'
import i18n from '@src/locales'

enum CustomerTagEditDialogEmitEventEnum {
  Change = 'change'
}

@Component({ 
  name: ComponentNameEnum.CustomerTagEditDialog
})
export default class CustomerTagEditDialog extends VC {
  
  @Prop({ default: '' }) readonly customerId: string | string[] | undefined
  @Prop({ default: () => [] }) readonly value: string[] | undefined 
  
  // 客户标签列表
  private customerTags: CustomerTag[] = []
  // 内部的值
  private internalValue: CustomerTag[] = []
  // 等待状态
  private pending: boolean = false
  // 标题
  private title: string = i18n.t('customer.detail.customerTagDialog.title') as string
  // 弹窗显示状态
  private visitableDialog: boolean = false
  
  get isValueEmpty(): boolean {
    return isEmpty(this.internalValue)
  }
  
  @Emit(CustomerTagEditDialogEmitEventEnum.Change)
  private emitValueChangedHandler(): CustomerTag[] {
    return this.getReturnValue()
  }
  
  private buildParams() {
    return {
      customerId: this.customerId,
      tagIds: this.getReturnValue().map(tag => tag.id)
    }
  }
  
  private cancel() {
    this.hide()
  }
  
  private confirm(): CustomerTag[] | void {
    if (!this.customerId) {
      this.hide()
      return this.emitValueChangedHandler()
    }
    
    Array.isArray(this.customerId) ? this.betchSave() : this.save()
  }
  
  /**
   * @description 获取客户标签列表
   * @return {void}
   */
  private fetchCustomerTagList(): Promise<boolean | void> {
    this.pending = true
    
    return (
      getCustomerTagList()
        .then(data => {
          if (!data?.success) {
            return Platform.alert(data?.message)
          }
          // @ts-ignore
          this.customerTags = data?.data || []
        })
        .finally(() => {
          this.pending = false
        })
    )
  }
  
  private goCustomerSettingTab() {
    openTabForSettingCustomerView()
  }
  
  private getReturnValue(): CustomerTag[] {
    return this.internalValue.filter(tag => tag.active)
  }
  
  /**
   * @description 获取属性列表
   * @return {Record<string, any>} 属性列表
   */  
  private getAttributes(): Record<string, any> {
    return {
      class: ComponentNameEnum.CustomerTagEditDialog,
      width: '700px',
      props: {
        width: '700px',
        title: this.title,
        show: this.visitableDialog
      },
      on: {
        'update:show': (value: boolean) => {
          this.visitableDialog = value
        }
      },
      directives: [
        {
          name: 'loading',
          value: this.pending
        }
      ]
    }
  }
  
  private hide() {
    this.visitableDialog = false
  }
  
  public outsideShow(value: CustomerTag[]): void {
    this.show(value)
  }
  
  private reset(): void {
    this.internalValue.forEach(tag => tag.active = false)
  }
  
  private async show(customerSelectedTags: CustomerTag[]): Promise<void> {
    this.visitableDialog = true;
    await this.fetchCustomerTagList()
    this.setSelectedTags(customerSelectedTags)
  }
  
  private setSelectedTags(customerSelectedTags: CustomerTag[]) {
    if (isEmpty(this.customerTags)) {
      this.internalValue = _.cloneDeep(customerSelectedTags).map(customerTag => {
        customerTag.active = true
        return customerTag
      })
      return
    }
    
    if (isEmpty(customerSelectedTags)) {
      this.internalValue = _.cloneDeep(this.customerTags)
      return
    }
    
    const customerSelectedTagsMap = fieldArrayToObject<CustomerTag>(
      customerSelectedTags, 
      (customerTag: CustomerTag) => {
        return customerTag[FieldArrayToObjectKeyEnum.TagId] || customerTag[FieldArrayToObjectKeyEnum.Id]
      }
    )
    
    this.internalValue = _.cloneDeep(this.customerTags).map(customerTag => {
      customerTag.active = Boolean(customerSelectedTagsMap[customerTag.id])
      return customerTag
    })
    
  }
  
  // 批量更新
  private betchSave(): Promise<boolean | void> {
    this.pending = true;
    return (batchUpdateCustomerTag({
      customerIds: this.customerId,
      tagIds: this.getReturnValue().map(tag => tag.id)
    }).then(data => {
      if (!data?.success) {
        return Platform.alert(data?.message)
      }

      this.pending = false;
      this.hide()
      //@ts-ignore
      this.$parent?.resetParams();
    }).finally(() => {
      this.pending = false
    }))
  }

  private save(): Promise<boolean | void> {
    const params = this.buildParams()
    
    return (
      setCustomerTag(params)
        .then((data) => {
          if (!data?.success) {
            return Platform.alert(data?.message)
          }
          
          this.emitValueChangedHandler()
          this.hide()
        })
    )
  }
  
  private toggleTagActive(tag: CustomerTag, index: number) {
    this.$set(this.internalValue[index], 'active', !tag.active)
  }
  
  private renderTip() {
    return (
      <div class="customer-tag-edit-tip">
        {i18n.t('customer.detail.customerTagDialog.emptyTip')}
      </div>
    )
  }
  
  private renderTags(): VNode[] {
    return this.internalValue.map((tag: CustomerTag, index: number) => this.renderTag(tag, index))
  }
  
  private renderTag(tag: CustomerTag, index: number): VNode {
    const className = ['customer-edit-tag', tag.active && 'customer-edit-tag-active']
    
    return (
      <div class={className} onClick={() => this.toggleTagActive(tag, index)}>
        { tag.tagName }
      </div>
    )
  }
  
  render(h: CreateElement) {
    const attrs = this.getAttributes()
    
    return (
      <base-modal {...attrs}>
        <div class='customer-edit-tag-list'>
          { this.renderTags() }
        </div>
        { this.isValueEmpty && this.renderTip() }
        <div slot='footer' class='dialog-footer'>
          <span disabled={this.pending} onClick={() => this.reset()}>
            {i18n.t('customer.detail.customerTagDialog.clear')}
          </span>
          <div>
            <el-button disabled={this.pending} onClick={() => this.cancel()}>
            {i18n.t('common.base.cancel')}
            </el-button>
            <el-button
              type='primary' 
              onClick={() => this.confirm()}
              disabled={this.pending}
            >
              {i18n.t('common.base.confirm')}
            </el-button>
          </div>
        </div>
      </base-modal>
    )
  }
}

